package jblip.base.resources;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import jblip.resources.Media;
import jblip.resources.Transport;
import jblip.resources.Update;
import jblip.resources.UpdateType;
import jblip.resources.User;
import jblip.resources.Media.MediaType;

class BaseUpdate implements Update, Comparable<Update> {
  private static final long serialVersionUID = 1L;

  /**
   * Gets update type from a given string.
   * 
   * @param type
   *          Textual representation of a type.
   * @return Type matching this method's argument or <code>null</code> if it
   *         doesn't correspond to any known type.
   */
  static UpdateType getUpdateType(String type) {
    if (type.equals("DirectedMessage")) {
      return UpdateType.DIRMSG;
    }

    if (type.equals("Status")) {
      return UpdateType.STATUS;
    }
    
    if (type.equals("PrivateMessage")) {
      return UpdateType.PRIVMSG;
    }
    
    if (type.equals("Notice")) {
      return UpdateType.NOTICE;
    }

    System.err.println("Unknown type: " + type);
    return null;
  }

  private final Integer id_;

  private final String body_;

  private final UpdateType type_;

  private final Transport transport_;

  private User src_user_;

  private User dst_user_;

  private String dst_user_login_;

  private String src_user_login_;

  private Date created_at_;

  private final List<Media> attached_pictures_;

  private String attached_pictures_path_;

  private Media attached_movie_;

  private String attached_movie_path_;

  private Media attached_recording_;

  private String attached_recording_path_;

  BaseUpdate(Integer id, String body, UpdateType type, Transport transport) {
    this.id_ = id;
    this.body_ = body;
    this.type_ = type;
    this.transport_ = transport;
    this.attached_pictures_ = new ArrayList<Media>();
  }

  public Integer getId() {
    return id_;
  }

  public String getBody() {
    return body_;
  }

  void setCreatedAt(Date date) {
    this.created_at_ = date;
  }

  public Date getCreatedAt() {
    return created_at_;
  }

  public Long getCreatedAtEpoch() {
    return (created_at_ == null ? 0L : created_at_.getTime());
  }

  void setDstUser(String login, User dst) {
    this.dst_user_ = dst;
    if (login != null) {
      this.dst_user_login_ = login;
    } else {
      this.dst_user_login_ = dst.getLogin();
    }
  }

  public User getDstUser() {
    return dst_user_;
  }

  public String getDstUserLogin() {
    return dst_user_login_;
  }

  void setSrcUser(String login, User src) {
    this.src_user_ = src;
    if (login != null) {
      this.src_user_login_ = login;
    } else {
      this.dst_user_login_ = src.getLogin();
    }
  }

  public User getSrcUser() {
    return src_user_;
  }

  public String getSrcUserLogin() {
    return src_user_login_;
  }

  public Transport getTransport() {
    return transport_;
  }

  public UpdateType getType() {
    return type_;
  }

  public List<Media> getAttachedPictures() {
    return attached_pictures_;
  }

  void addPicture(Media pict) {
    this.attached_pictures_.add(pict);
  }

  @Override
  public String getAttachedPicturesPath() {
    return attached_pictures_path_;
  }

  void setAttachedPicturesPath(String path) {
    this.attached_pictures_path_ = path;
  }

  @Override
  public Media getAttachedMovie() {
    return attached_movie_;
  }

  void setAttachedMovie(Media movie) {
    if (movie.getType().equals(MediaType.MOVIE)) {
      this.attached_movie_ = movie;
    } else {
      throw new IllegalArgumentException("Media not of movie type");
    }
  }

  @Override
  public String getAttachedMoviePath() {
    return attached_movie_path_;
  }

  void setAttachedMoviePath(String path) {
    this.attached_movie_path_ = path;
  }

  @Override
  public Media getAttachedRecording() {
    return attached_recording_;
  }

  void setAttachedRecording(Media recording) {
    if (recording.getType().equals(MediaType.RECORDING)) {
      this.attached_recording_ = recording;
    } else {
      throw new IllegalArgumentException("Media not of audio recording type");
    }
  }

  @Override
  public String getAttachedRecordingPath() {
    return attached_recording_path_;
  }

  void setAttachedRecordingPath(String path) {
    this.attached_recording_path_ = path;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Update) {
      final Update upd = (Update) obj;
      return upd.getId() == this.getId();
    }
    return false;
  }
  
  @Override
  public int compareTo(Update upd) {
    return this.getId() - upd.getId();
  }
}
